#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>  // 5.x版本
#include <Ticker.h>
#include <stdlib.h>       // 用于随机数（模拟传感器）

#define LED_PIN 2        
#define WIFI_SSID "EESP8266"  
#define WIFI_PASSWORD "12345678"  

// OneNet MQTT配置（需与平台一致）
#define MQTT_CLIENT_ID "test"        
#define MQTT_USERNAME "0PiA53nYkI"   // 产品ID
#define MQTT_PASSWORD "version=2018-10-31&res=products%2F0PiA53nYkI%2Fdevices%2Ftest&et=2810313550&method=md5&sign=IJUBs0uHANOiaIfkKmgxvg%3D%3D"
#define MQTT_SERVER "183.230.40.96"  
#define MQTT_PORT 1883               
#define MQTT_TOPIC_REPORT "$sys/0PiA53nYkI/test/thing/property/post"  // 物模型上报主题
#define SERVICE_ID "Detect"          // 平台产品的“服务ID”（与产品名称一致）

WiFiClient espClient;
PubSubClient client(espClient);
Ticker timer;          
int temp = 25;         // 模拟温度（需替换为传感器读取）
int humi = 50;         // 模拟湿度（需替换为传感器读取）
bool fire = false;     // 模拟火焰检测（bool类型）
int smoke_temp = 0;    // 模拟烟雾浓度（int32类型）
unsigned int msgId = 1;
bool needSendData = false;  

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH); 
  
  Serial.begin(115200);
  Serial.println("初始化系统...");
  
  randomSeed(analogRead(0)); // 初始化随机数（模拟传感器用）
  connectWiFi();
  client.setServer(MQTT_SERVER, MQTT_PORT);
  client.setCallback(callback);
  connectMQTT();
  
  timer.attach(2, [](){ needSendData = true; }); // 2秒触发一次上报
}

void loop() {
  static unsigned long lastStatus = 0;
  if (millis() - lastStatus > 5000) {
    Serial.print("MQTT状态: ");
    Serial.println(client.state()); // 调试用
    lastStatus = millis();
  }
  
  if (needSendData && client.connected()) {
    sendData();
    needSendData = false;
    // 模拟传感器数据变化（需替换为实际传感器逻辑）
    temp += random(-2, 3);  
    humi += random(-5, 6);   
    fire = random(0, 2);     // 0:无火焰, 1:有火焰
    smoke_temp += random(-10, 11); 
    // 限制范围（根据传感器实际值调整）
    temp = constrain(temp, -20, 60);  
    humi = constrain(humi, 0, 100);   
    smoke_temp = constrain(smoke_temp, 0, 500);
  }
  
  if (!client.connected()) connectMQTT();
  client.loop();
  
  if (WiFi.status() != WL_CONNECTED) connectWiFi();
  
  yield();
  delay(50);
}

void connectWiFi() {
  Serial.print("连接WiFi: ");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
  digitalWrite(LED_PIN, LOW);
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(200);
    yield();
    if (millis() - start > 10000) {
      Serial.println("\nWiFi超时，重启...");
      ESP.restart();
    }
  }
  digitalWrite(LED_PIN, HIGH);
  Serial.println("\nWiFi已连接");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
}

void connectMQTT() {
  Serial.print("连接OneNet MQTT: ");
  digitalWrite(LED_PIN, LOW);
  
  unsigned long start = millis();
  while (!client.connected()) {
    Serial.print(".");
    yield();
    if (client.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
      digitalWrite(LED_PIN, HIGH);
      Serial.println("\nMQTT已连接");
      if (client.subscribe(MQTT_TOPIC_REPORT)) { // 订阅下行主题（根据平台调整）
        Serial.println("已订阅命令主题");
      } else {
        Serial.println("订阅失败");
      }
      break;
    }
    if (millis() - start > 15000) {
      Serial.println("\nMQTT超时，重启...");
      ESP.restart();
    }
    delay(1000);
  }
}

// 按OneNet物模型格式上报数据（包含所有功能点）
void sendData() {
  StaticJsonBuffer<300> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  
  root["version"] = "1.0";
  root["method"] = "thing.property.post"; // 物模型上报方法
  root["id"] = msgId++;
  root["service_id"] = SERVICE_ID;        // 平台产品的服务ID（必须匹配）
  
  JsonObject& params = root.createNestedObject("params");
  params["temp"] = temp;       // 温度（int32）
  params["humi"] = humi;       // 湿度（int32）
  params["fire"] = fire;       // 火焰（bool）
  params["smoke_temp"] = smoke_temp; // 烟雾浓度（int32）
  
  char payload[300];
  root.printTo(payload, sizeof(payload));
  
  if (client.publish(MQTT_TOPIC_REPORT, payload)) {
    Serial.print("上报成功: ");
    Serial.println(payload);
    digitalWrite(LED_PIN, LOW);
    delay(30);
    digitalWrite(LED_PIN, HIGH);
  } else {
    Serial.println("上报失败");
    Serial.print("MQTT状态: ");
    Serial.println(client.state());
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("收到主题 [");
  Serial.print(topic);
  Serial.print("] 消息: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  
  digitalWrite(LED_PIN, LOW);
  delay(30);
  digitalWrite(LED_PIN, HIGH);
  
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(payload);
  if (root.success() && root.containsKey("params")) {
    JsonObject& params = root["params"];
    if (params.containsKey("led")) {
      int ledState = params["led"];
      digitalWrite(LED_PIN, ledState ? HIGH : LOW);
      Serial.print("LED状态: ");
      Serial.println(ledState);
    }
  } else {
    Serial.println("命令解析失败");
  }
}